import 'terms.dart';

// 复合术语判定
Terms judgeCompositeTerms(Board board, ChessStep chessStep,
    {List<ChessStep>? selfStepList,
    List<ChessStep>? oppositeStepList,
    int? distance,
    TermsCoordinates? descCoordinates,
    int ss2 = 0}) {
  printInfo('进入复合术语判定');

  /// 重新判定肩冲
  Terms reJudgeShoulderHit() {
    return Terms.shoulderHit;
  }

  /// 重新判定碰
  Terms reJudgePoke() {
    return Terms.poke;
  }

  /// 重新判断点
  Terms reJudgeDot() {
    return Terms.dot;
  }

  /// 1S1 * 1S4
  List<ChessStep> s1List = sCount(board, chessStep, 1, false);
  int s1 = s1List.length;
  List<ChessStep> s4List = sCount(board, chessStep, 1, true);
  int s4 = s4List.length;
  List<ChessStep> s5List = sCount(board, chessStep, 2, true);
  int s5 = s5List.length;
  List<ChessStep> s2List = sCount(board, chessStep, 2, false);
  int s2 = s2List.length;
  // printInfo('s2:$s2');
  ChessStep coordinate1;
  ChessStep coordinate5;
  if (ss2 != 0) {
    s2 = ss2;
  }
  if (s1 == 1 && s4 == 1) {
    var coordinate1 = s1List.first;
    var coordinate4 = s4List.first;

    if ((coordinate1.x == coordinate4.x &&
            coordinate1.x == changedX(chessStep)) ||
        (coordinate1.y == coordinate4.y &&
            coordinate1.y == changedY(chessStep))) {
      return Terms.top;
    }

    /// 1S1 * 1S2 * 1S4
    if (s2 == 1) {
      var coordinate2 = s2List.first;
      if ((changedX(chessStep) == coordinate1.x &&
              changedX(chessStep) == coordinate4.x) ||
          (changedY(chessStep) == coordinate1.y &&
              changedY(chessStep) == coordinate4.y)) {
        return Terms.top;
      }
      if ((coordinate1.y == coordinate2.y && coordinate1.x == coordinate4.x) ||
          (coordinate1.x == coordinate2.x && coordinate1.y == coordinate4.y)) {
        return Terms.top;
      } else if (coordinate1.x != coordinate2.x &&
          coordinate1.y != coordinate2.y) {
        return Terms.crush;
      }
    } else if (s2 == 2) {
      /// 1S1 * 2S2 * 1S4
      if (s2List.every(
          (value) => value.x == coordinate1.x || coordinate1.y == value.y)) {
        return Terms.attach;
      } else {
        return Terms.crush;
      }
    } else if (s2 > 2) {
      /// 1S1 * 3S2 * 1S4
      return Terms.crush;
    }

    // 忽略S2并入1S4 * 1S1 (贴系列)
    // if (coordinate1!.x == coordinate2.x || coordinate1.y == coordinate2.y) {
    //   return Terms.attach;
    // }

    /// 1S1 * 1S4 * 1S5
    if (s5 == 1) {
      coordinate5 = s5List.first;
      if ((coordinate4.y == coordinate5.y && coordinate1.x == coordinate5.x) ||
          coordinate4.x == coordinate5.x && coordinate1.y == coordinate5.y) {
        return Terms.turn;
      } else if ((coordinate4.y == changedY(chessStep) &&
              coordinate1.y == coordinate5.y) ||
          (coordinate4.x == changedX(chessStep) &&
              coordinate1.x == coordinate5.x)) {
        return Terms.resist;
      }
    } else if (s5 > 1) {
      return Terms.resist;
    }
  }

  /// 2S5*1S1
  if (s1 == 1 && s5 == 2) {
    coordinate1 = s1List.first;
    var s51 = s5List[0];
    var s52 = s5List[1];
    if ((s51.x == s52.x && s51.x == coordinate1.x) ||
        (s51.y == s52.y && s51.y == coordinate1.y)) {
      return Terms.resist;
    }
  }

  /// 1S1 * 1S5
  if (s1 == 1 && s5 == 1) {
    coordinate1 = s1List.first;
    coordinate5 = s5List.first;
    if (coordinate1.x == coordinate5.x || coordinate1.y == coordinate5.y) {
      var terms = backTerms(2, board);
      printInfo('前2手的术语：$terms');
      if (terms.contains(Terms.pull.desc)) {
        return Terms.doublePull;
      } else {
        return Terms.pull;
      }
    } else {
      if (s4 == 1) {
        ChessStep coordinate4 = s4List.first;
        if (s2List.isNotEmpty) {
          var coordinate2 = s2List.first;
          if ((coordinate4.x == changedX(chessStep) &&
                  coordinate4.x == coordinate2.x) ||
              (coordinate4.y == changedY(chessStep) &&
                  coordinate4.y == coordinate2.y)) {
            return Terms.top;
          } else {
            return Terms.resist;
          }
        }
      } else {
        return Terms.sharpTop;
      }
    }
  }

  /// 1S1*1S4(贴系列)
  if (s1 == 1 && s4 == 1) {
    ChessStep coordinate4 = s4List.first;
    coordinate1 = s1List.first;
    if (coordinate1.y == coordinate4.y || coordinate1.x == coordinate4.x) {
      return Terms.top;
    } else {
      switch (judgeFromAbstractDirection(board, chessStep)) {
        case AbstractDirection.specialDot:
          if (isOneOne(descCoordinates!)) {
            return Terms.crowd;
          }
          if (isTwoTwo(descCoordinates) ||
              isThreeThree(descCoordinates) ||
              isStar(descCoordinates)) {
            // printInfo('我进来了');
            // 进入方向复合判定
            return directionTerms(s1, s4,
                nextStep: chessStep,
                board: board,
                selfStepList: selfStepList,
                distanceSquared: distance ?? 0,
                oppositeStepList: oppositeStepList);
          }
        // 抽象特殊边角
        case AbstractDirection.specialSideCornerLeft:
          if (changedY(chessStep) == coordinate1.y) {
            if (changedX(chessStep) > coordinate1.x) {
              return Terms.press;
            } else {
              return Terms.climb;
            }
          } else {
            // 抽象左右方向
            if (changedX(chessStep) == coordinate1.x) {
              if (changedY(chessStep) == coordinate4.y) {
                // 当前棋在S4的抽象上方向：贴
                if (changedX(chessStep) > coordinate4.x) {
                  return Terms.attach;
                } else {
                  return Terms.resist;
                }
              }
            }
          }
        case AbstractDirection.specialSideCornerBottom:
          if (changedX(chessStep) == coordinate1.x) {
            if (changedY(chessStep) > coordinate1.y) {
              return Terms.press;
            } else {
              return Terms.climb;
            }
          } else {
            if (changedY(chessStep) == coordinate1.y) {
              if (changedX(chessStep) == coordinate4.x) {
                // 当前棋在S4的抽象上方向：贴
                if (changedY(chessStep) > coordinate4.y) {
                  return Terms.attach;
                } else {
                  return Terms.resist;
                }
              }
            }
          }
        case AbstractDirection.specialSideCornerRight:
          if (changedY(chessStep) == coordinate1.y) {
            if (changedX(chessStep) < coordinate1.x) {
              return Terms.press;
            } else {
              return Terms.climb;
            }
          } else {
            if (changedX(chessStep) == coordinate1.x) {
              if (changedY(chessStep) == coordinate4.y) {
                // 当前棋在S4的抽象上方向：贴
                if (changedX(chessStep) < coordinate4.x) {
                  return Terms.attach;
                } else {
                  return Terms.resist;
                }
              }
            }
          }
        case AbstractDirection.specialSideCornerTop:
          if (changedX(chessStep) == coordinate1.x) {
            if (changedY(chessStep) < coordinate1.y) {
              return Terms.press;
            } else {
              return Terms.climb;
            }
          } else {
            if (changedY(chessStep) == coordinate1.y) {
              if (changedX(chessStep) == coordinate4.x) {
                // 当前棋在S4的抽象上方向：贴
                if (changedY(chessStep) < coordinate4.y) {
                  return Terms.attach;
                } else {
                  return Terms.resist;
                }
              }
            }
          }
          return Terms.crowd;
        case AbstractDirection.middle:
          return Terms.attach;
      }
    }
  }

  /// 2S2*1S4(长变系列)
  if (s2 == 2 && s4 == 1) {
    var coordinate4 = s4List.first;
    if (s2List.every(
        (value) => value.x != coordinate4.x && value.y != coordinate4.y)) {
      return Terms.stretch;
    } else {
      return Terms.long;
    }
  }

  // 1S2*1S4（长系列）
  if (s2 == 1 && s4 == 1) {
    ChessStep coordinate4 = s4List.first;
    ChessStep coordinate2 = s2List.first;
    if (coordinate2.x != coordinate4.x && coordinate2.y != coordinate4.y) {
      return Terms.stretch;
    }

    /// 二二：x2或y2在一线时：长，否则：退
    /// 三三：x2或y2在二线时：长，否则：退
    /// 星位：x2或y2在三线时：长，否则：退
    if (isTwoTwo(descCoordinates!)) {
      if (coordinate2.x == 1 ||
          coordinate2.x == 19 ||
          coordinate2.y == 1 ||
          coordinate2.y == 19) {
        return Terms.long;
      } else {
        return Terms.back;
      }
    } else if (isThreeThree(descCoordinates)) {
      if (coordinate2.x == 2 ||
          coordinate2.x == 17 ||
          coordinate2.y == 2 ||
          coordinate2.y == 17) {
        return Terms.long;
      } else {
        return Terms.back;
      }
    } else if (isStar(descCoordinates)) {
      if (coordinate2.x == 3 ||
          coordinate2.x == 16 ||
          coordinate2.y == 3 ||
          coordinate2.y == 16) {
        return Terms.long;
      } else {
        return Terms.back;
      }
    }
    if (isOneOne(descCoordinates)) {
      return Terms.crowd;
    }
    // printInfo('我进来了');
    switch (judgeFromAbstractDirection(board, chessStep)) {
      case AbstractDirection.specialDot:
        if (isTwoTwo(descCoordinates) ||
            isThreeThree(descCoordinates) ||
            isStar(descCoordinates)) {
          // 当前手在S4的抽象上方向:⻓ 当前棋在S4的抽象下方向:立
          if (changedX(chessStep) == coordinate4.x) {
            if (changedY(chessStep) > coordinate4.y) {
              return Terms.long;
            } else {
              return Terms.stand;
            }
          }
        }

      case AbstractDirection.middle:
        return Terms.long;

      case AbstractDirection.specialSideCornerLeft:
        // 当前棋在S4的抽象上方向:⻓ 当前棋在S4的抽象下方向:立
        // 当前棋在S4的抽象左 、右方向 S2在S4的抽象上方向:退 S2在S4的抽象下方向:长
        if (changedY(chessStep) == coordinate4.y) {
          if (changedX(chessStep) > coordinate4.x) {
            return Terms.long;
          } else {
            return Terms.stand;
          }
        }
        if (changedX(chessStep) == coordinate4.x) {
          if (coordinate2.y == coordinate4.y) {
            if (coordinate2.x > coordinate4.x) {
              return Terms.back;
            } else {
              return Terms.long;
            }
          }
        }
      case AbstractDirection.specialSideCornerBottom:
        if (changedX(chessStep) == coordinate4.x) {
          if (changedY(chessStep) > coordinate4.y) {
            return Terms.long;
          } else {
            return Terms.stand;
          }
        }
        if (changedY(chessStep) == coordinate4.y) {
          if (coordinate2.x == coordinate4.x) {
            if (coordinate2.y > coordinate4.y) {
              return Terms.back;
            } else {
              return Terms.long;
            }
          } else {
            return Terms.long;
          }
        }
      case AbstractDirection.specialSideCornerRight:
        if (changedY(chessStep) == coordinate4.y) {
          if (changedX(chessStep) < coordinate4.x) {
            return Terms.long;
          } else {
            return Terms.stand;
          }
        }
        if (changedX(chessStep) == coordinate4.x) {
          if (coordinate2.y == coordinate4.y) {
            if (coordinate2.x < coordinate4.x) {
              return Terms.back;
            } else {
              return Terms.long;
            }
          }
        }
      case AbstractDirection.specialSideCornerTop:
        if (changedX(chessStep) == coordinate4.x) {
          if (changedY(chessStep) < coordinate4.y) {
            return Terms.long;
          } else {
            return Terms.stand;
          }
        }
        if (changedY(chessStep) == coordinate4.y) {
          if (coordinate2.x == coordinate4.x) {
            if (coordinate2.y < coordinate4.y) {
              return Terms.back;
            } else {
              return Terms.long;
            }
          }
        }
    }
  }

  /// 1S1*1S6
  int s6 = sCount(board, chessStep, 4, true).length;
  if (s1 == 1 && s6 == 1) {
    return Terms.depend;
  }

  /// 0S4*1S1(碰系列)
  if (s4 == 0 && s1 == 1) {
    coordinate1 = s1List.first;
    switch (judgeFromAbstractDirection(board, chessStep)) {
      case AbstractDirection.specialDot:
        if (isTwoTwo(descCoordinates!)) {
          return Terms.holdTwoTwo;
        } else if (isThreeThree(descCoordinates)) {
          return Terms.holdThreeThree;
        } else if (isStar(descCoordinates)) {
          return Terms.depend;
        }

      case AbstractDirection.middle:
        return Terms.poke;

      case AbstractDirection.specialSideCornerLeft:
        if (changedY(chessStep) == coordinate1.y) {
          if (changedX(chessStep) > coordinate1.x) {
            return reJudgePoke();
          } else {
            return isDependOrHold(descCoordinates!);
          }
        } else {
          if (changedX(chessStep) == coordinate1.x) {
            return Terms.depend;
          }
        }
      case AbstractDirection.specialSideCornerBottom:
        if (changedX(chessStep) == coordinate1.x) {
          if (changedY(chessStep) > coordinate1.y) {
            return reJudgePoke();
          } else {
            return isDependOrHold(descCoordinates!);
          }
        } else {
          if (changedY(chessStep) == coordinate1.y) {
            return Terms.depend;
          }
        }
      case AbstractDirection.specialSideCornerRight:
        if (changedY(chessStep) == coordinate1.y) {
          if (changedX(chessStep) < coordinate1.x) {
            return reJudgePoke();
          } else {
            return isDependOrHold(descCoordinates!);
          }
        } else {
          if (changedX(chessStep) == coordinate1.x) {
            return Terms.depend;
          }
        }
      case AbstractDirection.specialSideCornerTop:
        if (changedX(chessStep) == coordinate1.x) {
          if (changedY(chessStep) < coordinate1.y) {
            return reJudgePoke();
          } else {
            return isDependOrHold(descCoordinates!);
          }
        } else {
          if (changedY(chessStep) == coordinate1.y) {
            return Terms.depend;
          }
        }
    }
  }

  /// 0S5*1S2(肩冲系列)
  if (s2 == 1 && s5 == 0) {
    var coordinate2 = s2List.first;
    // print('descCoordinates: ${descCoordinates!.direction}');
    switch (judgeFromAbstractDirection(board, chessStep)) {
      case AbstractDirection.specialDot:
        if (isOneOne(descCoordinates!)) {
          return Terms.dotOneOne;
        } else if (isTwoTwo(descCoordinates)) {
          // y<y2
          if (changedY(chessStep) < coordinate2.y) {
            return Terms.dotTwoTwo;
          } else {
            return Terms.flail;
          }
        } else if (isThreeThree(descCoordinates)) {
          if (changedY(chessStep) < coordinate2.y) {
            return Terms.dotThreeThree;
          } else {
            return reJudgeShoulderHit();
          }
        } else if (isStar(descCoordinates)) {
          if (changedY(chessStep) < coordinate2.y) {
            return Terms.dot; // 点
          } else {
            return reJudgeShoulderHit();
          }
        }
      case AbstractDirection.middle:
        return Terms.shoulderHit;
      case AbstractDirection.specialSideCornerLeft:
        if (changedX(chessStep) < coordinate2.x) {
          return reJudgeDot();
        } else {
          return reJudgeShoulderHit();
        }
      case AbstractDirection.specialSideCornerBottom:
        if (changedY(chessStep) < coordinate2.y) {
          return reJudgeDot();
        } else {
          return Terms.shoulderHit;
        }
      case AbstractDirection.specialSideCornerRight:
        if (changedX(chessStep) > coordinate2.x) {
          return reJudgeDot();
        } else {
          return reJudgeShoulderHit();
        }
      case AbstractDirection.specialSideCornerTop:
        if (changedY(chessStep) > coordinate2.y) {
          return reJudgeDot();
        } else {
          return reJudgeShoulderHit();
        }
    }
  }

  return Terms.none;
}

/// 靠或托
Terms isDependOrHold(TermsCoordinates descCoordinates) {
  if (isFourLine(descCoordinates)) {
    return Terms.depend;
  } else if (isOneLine(descCoordinates) ||
      isTwoLine(descCoordinates) ||
      isThreeLine(descCoordinates)) {
    return Terms.hold;
  }
  return Terms.none;
}
